package com.ls.fw.search.solrj.support.builders;

import static com.ls.fw.search.solrj.domain.SolrConstants.SCORE_OP;
import static com.ls.fw.search.solrj.utils.AnnotationUtils.initFullTextFieldsPropertiesMap;
import static com.ls.fw.search.solrj.utils.QueryUtils.PARAMS_JOINER;
import static com.ls.fw.search.solrj.utils.QueryUtils.getExactMatchField;
import static com.ls.fw.search.solrj.utils.QueryUtils.getMatchPatternAndScore;

import java.util.List;

import com.google.common.collect.Lists;
import com.ls.fw.search.solrj.support.WildcardPadding;
import com.ls.fw.search.solrj.support.annotation.FullTextSearchField;



/**
 * Builder class that helps in the creation process of query patterns for classes annotated with
 * {@link FullTextSearchField}.
 */
public class FullTextQueryStringBuilder extends QueryStringBuilderBase {

  /**
   * Private default constructor.
   */
  private FullTextQueryStringBuilder(Class<?> annotatedClass) {
    super(annotatedClass);
  }

  public static FullTextQueryStringBuilder create(Class<?> annotatedClass) {
    return new FullTextQueryStringBuilder(annotatedClass);
  }


  /**
   * Helper method that sets the parameters for full text search param "q".
   * It will also add the optional query function.
   */
  @Override
  protected void initTemplates(Class<?> annotatedClass) {
    List<String> fullTextQueryComponents = Lists.newArrayList();
    List<String> phraseQueryComponents = Lists.newArrayList();

    List<FullTextSearchField> fullTextSearchFields = initFullTextFieldsPropertiesMap(annotatedClass);
    if (!fullTextSearchFields.isEmpty()) {
      for (FullTextSearchField field : fullTextSearchFields) {
        String exactMatchField = getExactMatchField(field);
        String exactMatchSubQuery =
            PARAMS_JOINER.join(exactMatchField, QUERY_PLACE_HOLDER + SCORE_OP + field.exactMatchScore());
        fullTextQueryComponents.add(exactMatchSubQuery);
        phraseQueryComponents.add(exactMatchSubQuery);
        setWildcardFilters(fullTextQueryComponents, phraseQueryComponents, field, exactMatchField);
        highlightedFields.add(field.highlightField().isEmpty() ? field.field() : field.highlightField());
      }
      queryTemplate = buildQueryExpression(fullTextQueryComponents);
      phraseQueryTemplate = buildQueryExpression(phraseQueryComponents);
    }
  }


  /**
   * Sets the filters for wildcard (if applicable) queries.
   */
  private static void setWildcardFilters(List<String> fullTextQueryComponents, List<String> phraseQueryComponents,
                                  FullTextSearchField field, String exactMatchField) {
    if (field.partialMatching() != WildcardPadding.NONE) {
      fullTextQueryComponents
        .add(PARAMS_JOINER.join(field.field(), getMatchPatternAndScore(field, QUERY_PLACE_HOLDER)));
      if (!exactMatchField.equals(field.field())) {
        phraseQueryComponents
          .add(PARAMS_JOINER.join(field.field(), QUERY_PLACE_HOLDER + SCORE_OP + field.partialMatchScore()));
      }
    }
  }
}
